在 JavaScript 中處理位元 (bit) 操作,通常需要直接使用位元運算子 (&, |, ^, ~),這在處理大量或複雜的二進位數據時可能會變得很繁瑣。為了簡化這個過程,我們介紹一個功能強大的工具類別:位元陣列 (BitArray)。這個類別將位元操作封裝在一個易於使用的 API 中,讓開發者能以更直觀的方式管理和操作位元級別的數據。
概述
位元陣列 是一個專為管理和操作二進位數據而設計的位元級別數據結構。它支援從字串或數值進行初始化,並可用於存放大量位元數據。其內部透過分頁機制進行管理,同時支援高效的位元運算功能。
初始化 位元陣列
建立 位元陣列 實例的方式非常靈活,您可以根據不同的需求進行初始化。
1. 建立指定長度的位元陣列
如果您需要一個預設長度、所有位元均為 0 的陣列,可以直接傳入一個數字。
// 使用數值初始化,代表位元的總數量
// 這會建立一個長度為 16,內容全為 0 的位元陣列
const bitArray = new 位元陣列(16);
console.log(bitArray.數量); // 輸出: 16
console.log(bitArray.轉為二進位字串()); // 輸出: "0000000000000000"
2. 從二進位字串解析
您可以直接使用一個二進位字串來建立位元陣列,字串中的空白字元會被自動忽略。
// 根據指定的二進位字串初始化
const bitArray = new 位元陣列("1010 1100");
console.log(bitArray.數量); // 輸出: 8
console.log(bitArray.轉為二進位字串()); // 輸出: "10101100"
3. 建立空的位元陣列
您也可以建立一個不含任何位元的空陣列,之後再動態操作。
// 初始化一個空的位元陣列
const bitArray = new 位元陣列();
console.log(bitArray.數量); // 輸出: 0
核心功能與方法
位元陣列 提供了豐富的方法來讀取和修改位元狀態。
讀取位元狀態
.數量: 一個唯讀屬性,用於取得當前陣列的總位元數量。.狀態(位元編號): 查詢指定位置的位元是否為 1。如果該位元為 1,返回true;否則返回false。.轉為二進位字串(): 將整個位元陣列以0和1的字串形式表示。
const bitArray = new 位元陣列("1011");
console.log(`總位元數: ${bitArray.數量}`); // 輸出: 總位元數: 4
console.log(`索引 0 的狀態: ${bitArray.狀態(0)}`); // 輸出: 索引 0 的狀態: false
console.log(`索引 1 的狀態: ${bitArray.狀態(1)}`); // 輸出: 索引 1 的狀態: true
console.log(`二進位字串: ${bitArray.轉為二進位字串()}`); // 輸出: 二進位字串: 1011
修改位元狀態
.設定狀態(位元編號, 狀態): 設定特定位元的狀態。第二個參數為布林值,true表示設為 1,false表示設為 0。.設定全部狀態(狀態): 將所有位元的狀態設定為指定值。.解析二進位字串(二進位字串): 使用新的二進位字串重新解析並設定整個陣列的內容。
這些方法都會返回當前的位元陣列實例,以支援鏈式調用。
const bitArray = new 位元陣列(8); // 初始為 "00000000"
// 透過鏈式調用設定多個位元
bitArray.設定狀態(1, true).設定狀態(3, true);
console.log(bitArray.轉為二進位字串()); // 輸出: "00001010"
// 將所有位元設為 1
bitArray.設定全部狀態(true);
console.log(bitArray.轉為二進位字串()); // 輸出: "11111111"
位元邏輯運算
這是 位元陣列 最強大的功能之一。它封裝了 AND、OR、XOR 和 NOT 四種基本邏輯運算,並回傳一個包含運算結果的新位元陣列實例。進行 AND、OR、XOR 運算時,兩個位元陣列的長度必須相同。
.and(另一個陣列): 執行位元AND(且) 運算。.or(另一個陣列): 執行位元OR(或) 運算。.xor(另一個陣列): 執行位元XOR(異或) 運算。.not(): 執行位元NOT(反轉) 運算。
const array1 = new 位元陣列("1100");
const array2 = new 位元陣列("1010");
const andResult = array1.and(array2);
console.log(`AND: ${andResult.轉為二進位字串()}`); // 輸出: AND: 1000
const orResult = array1.or(array2);
console.log(`OR: ${orResult.轉為二進位字串()}`); // 輸出: OR: 1110
const xorResult = array1.xor(array2);
console.log(`XOR: ${xorResult.轉為二進位字串()}`); // 輸出: XOR: 0110
const notResult = array1.not();
console.log(`NOT (對 array1): ${notResult.轉為二進位字串()}`); // 輸出: NOT (對 array1): 0011
複製陣列
如果您需要一個完全獨立的副本,可以使用 .複製() 方法。
const original = new 位元陣列("101");
const copied = original.複製();
// 修改複本不會影響原始物件
copied.設定狀態(0, true);
console.log(`原始: ${original.轉為二進位字串()}`); // 輸出: 原始: 101
console.log(`複本: ${copied.轉為二進位字串()}`); // 輸出: 複本: 101
編輯說明:上述範例中,由於 位元陣列("101") 的索引 0 原始值為 1 (true),設定狀態(0, true) 不會改變其值。若要展示差異,應設為 false。
實際應用範例
範例 1:權限管理系統
class 權限管理 {
constructor() {
// 定義權限位元
this.權限 = {讀取: 0, 寫入: 1, 執行: 2, 刪除: 3, 管理: 4};
}
建立用戶權限(權限列表) {
const 用戶權限 = new 位元陣列(8);
權限列表.forEach(權限名稱 => {
if (this.權限[權限名稱] !== undefined) {
用戶權限.設定(this.權限[權限名稱]);
}
});
return 用戶權限;
}
檢查權限(用戶權限, 需要權限) {
const 需要位元 = this.權限[需要權限];
return 用戶權限.取得(需要位元);
}
添加權限(用戶權限, 新權限) {
const 權限位元 = this.權限[新權限];
用戶權限.設定(權限位元);
}
移除權限(用戶權限, 移除權限) {
const 權限位元 = this.權限[移除權限];
用戶權限.清除(權限位元);
}
}
範例 2:狀態追蹤系統
class 狀態追蹤 {
constructor(項目數量) {
this.已完成 = new 位元陣列(項目數量);
this.進行中 = new 位元陣列(項目數量);
this.已暫停 = new 位元陣列(項目數量);
}
開始項目(索引) {
this.進行中.設定(索引);
this.已完成.清除(索引);
this.已暫停.清除(索引);
}
完成項目(索引) {
this.已完成.設定(索引);
this.進行中.清除(索引);
this.已暫停.清除(索引);
}
暫停項目(索引) {
this.已暫停.設定(索引);
this.進行中.清除(索引);
}
取得統計() {
return {
已完成數量: this.已完成.計數(),
進行中數量: this.進行中.計數(),
已暫停數量: this.已暫停.計數(),
完成率: (this.已完成.計數() / this.已完成.長度 * 100).toFixed(1) + '%',
};
}
取得進度報告() {
const 統計 = this.取得統計();
return `
專案進度報告:
- 已完成:${統計.已完成數量} 項
- 進行中:${統計.進行中數量} 項
- 已暫停:${統計.已暫停數量} 項
- 完成率:${統計.完成率} `;
}
}
// 使用範例
const 專案追蹤 = new 狀態追蹤(10);
// 模擬專案進度 專案追蹤.開始項目(0); 專案追蹤.開始項目(1); 專案追蹤.完成項目(0); 專案追蹤.暫停項目(1); 專案追蹤.開始項目(2);
console.log(專案追蹤.取得進度報告());
範例 3:布隆過濾器實作
class 布隆過濾器 {
constructor(大小, 雜湊函數數量 = 3) {
this.位元陣列 = new 位元陣列(大小);
this.大小 = 大小;
this.雜湊函數數量 = 雜湊函數數量;
}
_雜湊(字串, 種子) {
let 雜湊值 = 0;
for (let i = 0; i < 字串.length; i++) {
雜湊值 = (雜湊值 * 31 + 字串.charCodeAt(i) + 種子) % this.大小;
}
return Math.abs(雜湊值);
}
添加(元素) {
for (let i = 0; i < this.雜湊函數數量; i++) {
const 位置 = this._雜湊(元素.toString(), i);
this.位元陣列.設定(位置);
}
}
可能包含(元素) {
for (let i = 0; i < this.雜湊函數數量; i++) {
const 位置 = this._雜湊(元素.toString(), i);
if (!this.位元陣列.取得(位置)) {
return false;
}
}
return true;
}
取得統計() {
const 設定位元數 = this.位元陣列.計數();
const 載入率 = (設定位元數 / this.大小 * 100).toFixed(2);
return {
設定位元數,
總位元數: this.大小,
載入率: 載入率 + '%',
};
}
}
// 使用範例
const 過濾器 = new 布隆過濾器(1000);
// 添加元素
const 用戶列表 = ['user1', 'user2', 'user3', 'user4', 'user5'];
用戶列表.forEach(用戶 => 過濾器.添加(用戶));
// 檢查元素
console.log('user1 存在?', 過濾器.可能包含('user1')); // true
console.log('user6 存在?', 過濾器.可能包含('user6')); // false (或可能的誤判)
console.log('過濾器統計:', 過濾器.取得統計());
結論
位元陣列 (BitArray) 類別提供了一個清晰、高階的 API 來處理 JavaScript 中的位元操作。無論是處理權限標誌、數據壓縮、還是其他需要精確控制位元的場景,它都能大大簡化開發流程,提高程式碼的可讀性和可維護性。